package com.ltu.util.ext.wx.wxCore;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ltu.util.datetime.DateTimeUtil;
import org.apache.commons.codec.digest.DigestUtils;

import com.ltu.util.xml.XmlUtils;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;

import lombok.extern.slf4j.Slf4j;

/**
 * @Description:
 * @author: 若尘
 * @date 2018年10月18日 上午11:31:39
 * @version V1.0
 */
@Slf4j
public class WeChatUtils {
	
	public volatile static List<String> excludeRepeatList = new ArrayList<String>();
	static List<String> excludeRepeatList3 = new ArrayList<String>();
	static List<String> excludeRepeatList2 = new ArrayList<String>();
	static List<String> openids = new ArrayList<String>();
	

	/**
	 * @time:2018年10月18日
	 * @author:若尘
	 * @Description: 统一回复微信服务器
	 * @param:@param response
	 * @param:@param returnvaleue
	 * @return:void
	 */
	public static void responseReplyMessage(HttpServletResponse response, String content) {

		PrintWriter pw;
		try {
			pw = response.getWriter();
			pw.write(content);
			pw.flush();
			pw.close();
		} catch (IOException e) {

			e.printStackTrace();
		}

	}

	/**
	 * 微信全网接入 事件消息
	 * 
	 * @param request
	 * @param response
	 * @param event
	 * @param toUserName
	 * @param fromUserName
	 * @throws Exception
	 */
	private static void replyEventMessage(HttpServletRequest request, HttpServletResponse response, String event,
			String toUserName, String fromUserName) throws Exception {
		String content = event + "from_callback";
		log.info("\n --------------事件回复消息  content=" + content + "   toUserName=" + toUserName + "   fromUserName="
				+ fromUserName);
		replyTextMessage(request, response, content, toUserName, fromUserName);
	}

	/**
	 * 回复微信服务器"文本消息"
	 * 
	 * @param request
	 * @param response
	 * @param content
	 * @param toUserName
	 * @param fromUserName
	 * @throws DocumentException
	 * @throws IOException
	 */
	public static void replyTextMessage(HttpServletRequest request, HttpServletResponse response, String content,
			String toUserName, String fromUserName) throws Exception {
		Long createTime = new Long(DateTimeUtil.getStampTime());
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		sb.append("<ToUserName><![CDATA[" + fromUserName + "]]></ToUserName>");
		sb.append("<FromUserName><![CDATA[" + toUserName + "]]></FromUserName>");
		sb.append("<CreateTime>" + createTime + "</CreateTime>");
		sb.append("<MsgType><![CDATA[text]]></MsgType>");
		sb.append("<Content><![CDATA[" + content + "]]></Content>");
		sb.append("</xml>");
		String replyMsg = sb.toString();

		String returnvaleue = "";
		try {
			String encodingAesKey = "";// 第三方平台组件加密密钥
			String appId = "";
			WXBizMsgCrypt pc = new WXBizMsgCrypt("", encodingAesKey, appId);
			returnvaleue = pc.encryptMsg(replyMsg, createTime.toString(), request.getParameter("nonce"));
			log.info("------------------加密后的返回内容 returnvaleue： " + returnvaleue);
		} catch (AesException e) {
			e.printStackTrace();
		}
		responseReplyMessage(response, returnvaleue);
	}

	/**
	 * 接收消息 排重
	 * 
	 * @param type
	 *            消息的类型： 1 文本 0 事件
	 * @param msgId
	 *            文本的内容
	 * @param FromUserName
	 *            消息的发送方,此处为openId
	 * @param CreateTime
	 *            消息创建的时间
	 * @return false 重复的 true 不重复
	 */
	public static boolean messageExcludeRepeat(int type, String msgId, String FromUserName, String CreateTime) {
		// 当数量大于10000时，删除
		if (excludeRepeatList.size() >= 10000) {
			excludeRepeatList.clear();
		}
		if (type == 1) {
			String key = msgId + FromUserName + CreateTime;
			// 判断该文本消息是否是重复的
			if (excludeRepeatList.contains(key)) {
				return false;
			}
			excludeRepeatList.add(key);
		} else {
			String key =  msgId + FromUserName + CreateTime;
			// 判断该事件消息是否是重复的
			if (excludeRepeatList.contains(key)) {
				return false;
			}
			excludeRepeatList.add(key);
		}
		return true;
	}

	/**
	 * 
	 * @date 2019年1月12日
	 * @author 若尘
	 * @Description 微信支付回调消息排重 包含返回true
	 * @param out_trade_no
	 * @param transaction_id
	 * @param time_end
	 * @param openid
	 * @param mch_id
	 * @return
	 * @return boolean
	 */

	public synchronized static boolean messageExcludeRepeat(String out_trade_no, String transaction_id, String time_end,
			String openid, String mch_id) {

		String key = out_trade_no + transaction_id + time_end + openid + mch_id;
		// //判断该文本消息是否是重复的
		if (excludeRepeatList.contains(key)) {
			return true;
		}
		// 当数量大于10000时，删除
		if (excludeRepeatList.size() >= 10000) {
			excludeRepeatList.clear();
		}
		excludeRepeatList.add(key);

		return false;
	}

	public synchronized static boolean QmMsgExcludeRepeat(String out_trade_no, String transaction_id, String time_end) {

		String key = out_trade_no + transaction_id + time_end;
		// 判断该文本消息是否是重复的
		if (excludeRepeatList2.contains(key)) {
			return true;
		}
		// 当数量大于10000时，删除
		if (excludeRepeatList2.size() >= 10000) {
			excludeRepeatList2.clear();
		}
		excludeRepeatList2.add(key);

		return false;
	}
	// 银联用到的消息排重
	public synchronized static boolean chinaMsgExcludeRepeat(String out_trade_no, String seqId, String time_end) {

		String key = out_trade_no + seqId + time_end;
		// 判断该文本消息是否是重复的
		if (excludeRepeatList.contains(key)) {
			return true;
		}
		// 当数量大于10000时，删除
		if (excludeRepeatList.size() >= 10000) {
			excludeRepeatList.clear();
		}
		excludeRepeatList.add(key);

		return false;
	}
		/**
		 * @date 2019年10月16日
		 * @author 若尘
		 * @Description微信支付通知用到的消息排重
		 * @param payRecord
		 * @param seqId
		 * @param time_end
		 */
	public synchronized static boolean wxPayMsgExcludeRepeat(String out_trade_no, String transaction_id, String time_end) {

		String key = out_trade_no + transaction_id + time_end;
		// 判断该文本消息是否是重复的
		if (excludeRepeatList3.contains(key)) {
			return true;
		}
		// 当数量大于10000时，删除
		if (excludeRepeatList3.size() >= 10000) {
			excludeRepeatList3.clear();
		}
		excludeRepeatList3.add(key);
		return false;
	}
	

	/**
	 * @time:2018年10月18日
	 * @author:若尘
	 * @Description: 响应支付回调至微信服务器
	 * @param:@param response
	 * @param:@param returnvaleue
	 * @return:void
	 */
	public static void responsePayMessage(HttpServletResponse response, String msg) {

		PrintWriter pw;
		try {
			Map<String, String> returnMsg = new HashMap<>();
			returnMsg.put("return_code", "SUCCESS");
			returnMsg.put("return_msg", msg);
			String content = XmlUtils.toXml(returnMsg);
			pw = response.getWriter();
			pw.write(content);
			pw.flush();
			pw.close();
		} catch (IOException e) {

			e.printStackTrace();
		}

	}
	/**
	 * @time:2018年10月18日
	 * @author:若尘
	 * @Description: 响应支付回调至微信服务器
	 * @param:@param response
	 * @param:@param returnvaleue
	 * @return:void
	 */
	public static void responseStrMsg(HttpServletResponse response, String msg) {
		
		PrintWriter pw;
		try {
//			Map<String, String> returnMsg = new HashMap<>();
//			returnMsg.put("code", "S");
//			returnMsg.put("return_msg", msg);
//			String content = XmlUtils.toXml(returnMsg);
			pw = response.getWriter();
			pw.write(msg);
			pw.flush();
			pw.close();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
	}

	/**
	 * @time:2018年10月18日
	 * @author:若尘
	 * @Description: 响应钱喵支付完成
	 * @param:@param response
	 * @param:@param returnvaleue
	 * @return:void
	 */
	public static void responsQmPayMsg(HttpServletResponse response, String msg) {

		PrintWriter pw;
		try {
			String content = msg;
			pw = response.getWriter();
			pw.write(content);
			pw.flush();
			pw.close();
		} catch (IOException e) {

			e.printStackTrace();
		}

	}

	public static boolean isContainOpenid(String openId) {
		if (openids.contains(openId)) {
			return true;
		}
		if (openids.size() > 10000) {
			openids.clear();
		}
		openids.add(openId);
		return false;

	}

	/**
	 * 
	 * @date 2018年12月28日
	 * @author 若尘
	 * @Description 签名验证 true通过 否则验证失败
	 */
	public static boolean verifySign(Map<String, Object> json, String payKey, String verifySign) {
		StringBuilder result = new StringBuilder();
		String key = "&key=" + payKey;
		String[] arr = new String[json.keySet().size()];
		json.keySet().toArray(arr);
		int len = arr.length;
		Arrays.sort(arr);// QueryString排序
		for (int i = 0; i < len; i++) {
			result.append(arr[i]);
			result.append("=");
			result.append(json.get(arr[i]));
			if (i < len - 1) {
				result.append("&");
			}
		}
		System.out.println("\n 排好序的字符串" + result);
		result.append(key);
		System.out.println("\n 等待加密的字符串：" + result);
		String sign = DigestUtils.md5Hex(result.toString()).toUpperCase();
		System.out.println("\n Md5加密后且转为大写的签名字符串：" + sign);
		return verifySign.equals(sign);

	}
	
	
	public static boolean verifySign2(Map<String, String> json, String payKey, String verifySign) {
		StringBuilder result = new StringBuilder();
		String key = "&key=" + payKey;
		String[] arr = new String[json.keySet().size()];
		json.keySet().toArray(arr);
		int len = arr.length;
		Arrays.sort(arr);// QueryString排序
		for (int i = 0; i < len; i++) {
			result.append(arr[i]);
			result.append("=");
			result.append(json.get(arr[i]));
			if (i < len - 1) {
				result.append("&");
			}
		}
		System.out.println("\n 排好序的字符串" + result);
		result.append(key);
		System.out.println("\n 等待加密的字符串：" + result);
		String sign = DigestUtils.md5Hex(result.toString()).toUpperCase();
		System.out.println("\n Md5加密后且转为大写的签名字符串：" + sign);
		return verifySign.equals(sign);
		
	}

}
